//*****************************************************************************
//
// uart_echo.c - Example for reading data from and writing data to the UART in
//               an interrupt driven fashion.
//
// Copyright (c) 2005-2011 Texas Instruments Incorporated.  All rights reserved.
// Software License Agreement
// 
// Texas Instruments (TI) is supplying this software for use solely and
// exclusively on TI's microcontroller products. The software is owned by
// TI and/or its suppliers, and is protected under applicable copyright
// laws. You may not combine this software with "viral" open-source
// software in order to form a larger program.
// 
// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
// DAMAGES, FOR ANY REASON WHATSOEVER.
// 
// This is part of revision 6852 of the EK-LM3S8962 Firmware Package.
//
//*****************************************************************************

#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/debug.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"
#include "rit128x96x4.h"
#include <stdio.h>
#include "ADC.h"
#include "blink.h"
#include "OS.h"


#define AddFifo(NAME,SIZE,TYPE, SUCCESS,FAIL) unsigned long volatile PutI ## NAME;unsigned long volatile GetI ## NAME;TYPE static Fifo ## NAME [SIZE]; void NAME ## Fifo_Init(void){PutI ## NAME= GetI ## NAME = 0;}  int NAME ## Fifo_Put (TYPE data){if(( PutI ## NAME - GetI ## NAME ) & ~(SIZE-1)){return(FAIL);} Fifo ## NAME[ PutI ## NAME &(SIZE-1)] = data; PutI ## NAME ## ++; return(SUCCESS);} int NAME ## Fifo_Get (TYPE *datapt){if( PutI ## NAME == GetI ## NAME ){return(FAIL); } *datapt = Fifo ## NAME[ GetI ## NAME &(SIZE-1)]; GetI ## NAME ## ++; return(SUCCESS);}
#define BACKSPACE 		0x08
#define CARRIAGERETURN 	0x0D
#define LINEFEED 		0x0A

//#define AddFifo(NAME,SIZE,TYPE, SUCCESS,FAIL) \
//unsigned long volatile PutI ## NAME;  \
//unsigned long volatile GetI ## NAME;  \ 
//TYPE static Fifo ## NAME [SIZE];      \ 
//void NAME ## Fifo_Init(void){         \ 
//  PutI ## NAME= GetI ## NAME = 0;     \ 
//}                                     \                                     
//int NAME ## Fifo_Put (TYPE data){      \ 
//  if(( PutI ## NAME - GetI ## NAME ) & ~(SIZE-1)){  \ 
//    return(FAIL);      \ 
//}                      \                      
//  Fifo ## NAME[ PutI ## NAME &(SIZE-1)] = data; \ 
//  PutI ## NAME ## ++;  \ 
//  return(SUCCESS);     \ 
//}                      \
//int NAME ## Fifo_Get (TYPE *datapt){  \ 
//  if( PutI ## NAME == GetI ## NAME ){ \ 
//    return(FAIL);      \ 
// }                     \              
//  *datapt = Fifo ## NAME[ GetI ## NAME &(SIZE-1)];  \ 
//  GetI ## NAME ## ++;  \ 
//  return(SUCCESS);     \ 
//}

AddFifo(Tx, 32, unsigned char, 1, 0)
AddFifo(Rx, 32, unsigned char, 1, 0)

int CommandComplete = 0;
int ADCRequest      = 0;
int BlinkyRequest   = 0;
const unsigned char ADCCommand[3]   = "ADC";
const unsigned char BlinkyCommand[6] = "Blinky";

//*****************************************************************************
//
//! \addtogroup example_list
//! <h1>UART Echo (uart_echo)</h1>
//!
//! This example application utilizes the UART to echo text.  The first UART
//! (connected to the FTDI virtual serial port on the evaluation board) will be
//! configured in 115,200 baud, 8-n-1 mode.  All characters received on the
//! UART are transmitted back to the UART.
//
//*****************************************************************************

//static const unsigned char* menuScreen = ["Lab 1 Demo Menu:/n1: Timer Start/n2:Timer Stop/n3:Timer Reset"];

//*****************************************************************************
//
// The error routine that is called if the driver library encounters an error.
//
//*****************************************************************************
#ifdef DEBUG
void
__error__(char *pcFilename, unsigned long ulLine)
{
}
#endif

//*****************************************************************************
//
// The UART interrupt handler.
//
//*****************************************************************************
void
UARTIntHandler(void)
{
    unsigned long ulStatus;
	unsigned char temp;
	

	int success = 1;

    //
    // Get the interrrupt status.
    //
    ulStatus = UARTIntStatus(UART0_BASE, true);
	
	//
	// Clear the interrupts
	//
	UARTIntClear(UART0_BASE, ulStatus);		
	
	//
	// Get all chars off of Recieve Hardware FIFO; Put on both receive and transmit software FIFOs
	//	
	while(success && UARTCharsAvail(UART0_BASE))
	{
		temp = 	UARTCharGetNonBlocking(UART0_BASE);
		success = RxFifo_Put(temp);
		if(success){
			TxFifo_Put(temp);
		}
		if(temp == CARRIAGERETURN){
			CommandComplete = 1;
			TxFifo_Put(LINEFEED);
		}
	}
	
	//
	// Put as many chars in Trasmit Software FIFO on Transmit Hardware FIFO as possible
	//
	success = TxFifo_Get(&temp);
	while(success){
		success = UARTCharPutNonBlocking(UART0_BASE, temp);
		success &= TxFifo_Get(&temp); 
	}

//    //
//    // Clear the asserted interrupts.
//    //
//    UARTIntClear(UART0_BASE, ulStatus);
//
//    //
//    // Loop while there are characters in the receive FIFO.
//    //
//    while(UARTCharsAvail(UART0_BASE))
//    {
//        //
//        // Read the next character from the UART and write it back to the UART.
//        //
//        UARTCharPutNonBlocking(UART0_BASE, UARTCharGetNonBlocking(UART0_BASE));
//    }
}

//*****************************************************************************
//
// Send a string to the UART.
//
//*****************************************************************************
void
UARTSend(unsigned char *pucBuffer, unsigned long ulCount)
{
    //
    // Loop while there are more characters to send.
    //

	int success = 1;
    while(ulCount-- && success)
    {
        //
        // Write the next character to the UART.
        //
        success = TxFifo_Put(*pucBuffer);
		pucBuffer++;
    }

//	while(ulCount--)
//	{
//		UARTCharPutNonBlocking(UART0_BASE, *pucBuffer++);
//	}

	
}

//*****************************************************************************
//
// Gets a char from the Fifo
//
//*****************************************************************************
int
UARTGet(unsigned char *buf)
{
	return RxFifo_Get(buf);
}

//*****************************************************************************
//
// This example demonstrates how to send a string of data to the UART.
//
//*****************************************************************************


int
main(void)
{
	unsigned char charGet;
	volatile unsigned char buf[32];
	unsigned char adcBuf[10];
	int bufIndex = 0;
	long ADCValue = 0;
	
	OS_Init();
	//
    // Set the clocking to run directly from the crystal.
    // SYSDIV_4 = 50MHz
	// Use PLL
	// Externl Crystal 8MHz
	//
    SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |
                   SYSCTL_XTAL_8MHZ);

    //
    // Initialize the OLED display and write status.
    //
    oLED_Init(1000000);
	
	TxFifo_Init();
	RxFifo_Init();

	 //
    // Enable the peripherals used by this example.
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

    //
    // Enable processor interrupts.
    //
    IntMasterEnable();

    //
    // Set GPIO A0 and A1 as UART pins.
    //
    GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
	//UARTFIFOEnable(UART0_BASE);

    //
    // Configure the UART for 115,200, 8-N-1 operation.
    //
    UARTConfigSetExpClk(UART0_BASE, SysCtlClockGet(), 115200,
                        (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
                         UART_CONFIG_PAR_NONE));

    // Initialize ADC
	ADC_Open();
	
	SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER2);

	// Initialize LED
	Blink_Init();

	//
    // Enable the UART interrupt.
    //
    IntEnable(INT_UART0);
	UARTFIFOLevelSet(UART0_BASE, UART_FIFO_TX1_8, UART_FIFO_RX4_8);
    UARTIntEnable(UART0_BASE, UART_INT_RX | UART_INT_RT | UART_INT_TX );

	UARTCharPutNonBlocking(UART0_BASE, '*');
	UARTCharPutNonBlocking(UART0_BASE, '*');
	UARTCharPutNonBlocking(UART0_BASE, BACKSPACE);
	UARTCharPutNonBlocking(UART0_BASE, BACKSPACE);
	UARTSend("Enter a command: ", 17);
	
		
	while(1)
	{
		if(CommandComplete){
			//oLED_Message(1,4,"COMMAND!",15);
			CommandComplete = 0;
			bufIndex = 0;

			while(RxFifo_Get(&charGet) && charGet != 0x0D){
				buf[bufIndex++] = charGet;
			}
			
			// Check for ADC Request
			ADCRequest = 1;
			for(bufIndex = 0;bufIndex < 3; bufIndex++){
				if(buf[bufIndex] != ADCCommand[bufIndex])
					ADCRequest = 0;
			}

			// Check for Blinky Request
			BlinkyRequest = 1;
			for(bufIndex = 0;bufIndex < 6; bufIndex++){
					if(buf[bufIndex] != BlinkyCommand[bufIndex])
						BlinkyRequest = 0;
			}

			if(ADCRequest){
				ADCValue = ADC_In(0);
				sprintf(adcBuf,"%i", ADCValue);
				oLED_Message(0,0,adcBuf,15);
				oLED_Message(0,1,"ADC",15);
			}
			else if(BlinkyRequest){
				oLED_Message(1,0,"Blinking Start",14);
				OS_AddPeriodicThread(&Blink, 10, 5);
			}
			else{
				UARTCharPutNonBlocking(UART0_BASE, '*');
				UARTCharPutNonBlocking(UART0_BASE, '*');
				UARTCharPutNonBlocking(UART0_BASE, BACKSPACE);
				UARTCharPutNonBlocking(UART0_BASE, BACKSPACE);
				UARTSend("InvalidCommand",16);
				TxFifo_Put(CARRIAGERETURN);
				TxFifo_Put(LINEFEED);
			}
		}
			 
	}
}

/*
int
main(void)
{
    //
    // Set the clocking to run directly from the crystal.
    //
    SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |
                   SYSCTL_XTAL_8MHZ);

    //
    // Initialize the OLED display and write status.
    //
    oLED_Init(1000000);
    oLED_StringDraw("UART Echo",            36,  0, 15);
    oLED_StringDraw("Port:   Uart 0",       12, 16, 15);
    oLED_StringDraw("Baud:   115,200 bps",  12, 24, 15);
    oLED_StringDraw("Data:   8 Bit",        12, 32, 15);
    oLED_StringDraw("Parity: None",         12, 40, 15);
    oLED_StringDraw("Stop:   1 Bit",        12, 48, 15);

    //
    // Enable the peripherals used by this example.
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

    //
    // Enable processor interrupts.
    //
    IntMasterEnable();

    //
    // Set GPIO A0 and A1 as UART pins.
    //
    GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);

    //
    // Configure the UART for 115,200, 8-N-1 operation.
    //
    UARTConfigSetExpClk(UART0_BASE, SysCtlClockGet(), 115200,
                        (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
                         UART_CONFIG_PAR_NONE));

    //
    // Enable the UART interrupt.
    //
    IntEnable(INT_UART0);
    UARTIntEnable(UART0_BASE, UART_INT_RX | UART_INT_RT);

    //
    // Prompt for text to be entered.
    //
    UARTSend((unsigned char *)"Enter text: ", 12);

    //
    // Loop forever echoing data through the UART.
    //
    while(1)
    {
    }
}*/
